//+------------------------------------------------------------------+
//|                      PieChart.mqh 饼图绘图画布类头文件           |
//|                版权所有 2000-2025, MetaQuotes Ltd.              |
//|                        官方网址: https://www.mql5.com            |
//+------------------------------------------------------------------+
#include "ChartCanvas.h"         // 引入图表绘制基础类 CChartCanvas

//+------------------------------------------------------------------+
//| CPieChart 类                                                      |
//| 功能：MT5 饼图专用绘图画布类，基于图表基础类实现单系列饼图渲染   |
//| 继承关系：public CChartCanvas（基于通用图表类，扩展饼图特有能力）|
//| 核心特性：                                                      |
//|  1. 支持单系列饼图（多分类数据占比可视化，数值需为正数）          |
//|  2. 自动处理小占比数据（低于阈值归为“其他”类别，避免图表拥挤）    |
//|  3. 支持数据标签灵活配置（显示描述符、数值、百分比，自动分左右布局）|
//|  4. 提供完整数据管理接口（批量设置、添加/插入/更新/删除单值）      |
//|  5. 继承基础图表组件控制（图例、描述符等可见性配置）              |
//+------------------------------------------------------------------+
class CPieChart : public CChartCanvas
  {
private:
   //--- 数据存储核心参数
   CArrayDouble     *m_values;           // 饼图数据存储指针（单系列数据，每个元素对应一个扇区的数值，需>0）

   //--- 饼图绘制几何参数（内部计算，用于定位与尺寸控制）
   int               m_x0;               // 饼图圆心 X 坐标（像素，基于数据绘制区域自动计算）
   int               m_y0;               // 饼图圆心 Y 坐标（像素，基于数据绘制区域自动计算）
   int               m_r;                // 饼图半径（像素，基于数据绘制区域宽高自动适配，确保圆形）

public:
   /**
    * @brief 构造函数：初始化饼图绘图画布实例
    * @details 调用父类 CChartCanvas 构造函数，默认配置允许显示的组件（图例、描述符、数值、百分比），
    *          并启用上述组件的显示（通过 AllowedShowFlags 和 ShowFlags 实现）
    */
                     CPieChart(void);

   /**
    * @brief 析构函数：销毁饼图绘图画布实例
    * @details 依赖父类 CChartCanvas 销毁 m_values 数据存储对象，自身无额外资源释放
    */
                    ~CPieChart(void);

   //--- 饼图画布创建接口（重写父类方法，初始化数据存储）
   /**
    * @brief 创建饼图画布资源（初始化尺寸、颜色格式及单系列数据存储）
    * @param name [in] 画布资源名称（用于标识图表在 MT5 中的对象名称）
    * @param width [in] 画布宽度（像素，必须 >0，建议与图表显示区域匹配）
    * @param height [in] 画布高度（像素，必须 >0，建议与图表显示区域匹配）
    * @param clrfmt [in] 颜色处理格式（默认 COLOR_FORMAT_XRGB_NOALPHA，无透明度，饼图扇区无重叠）
    * @return bool - 操作结果：true=画布创建与数据存储初始化成功，false=失败（如内存分配失败）
    * @note 内部会创建 CArrayDouble 对象用于存储单系列数据，并将父类 m_data 指针指向该对象
    */
   virtual bool      Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA);

   //--- 数据管理接口（饼图单系列数据的批量设置与单值操作）
   /**
    * @brief 批量设置饼图数据（覆盖原有数据，适用于初始化场景）
    * @param value [in] 数据数组（double 类型，每个元素需>0，对应扇区数值）
    * @param text [in] 描述符数组（string 类型，与数据数组长度一致，对应每个扇区的名称/标签）
    * @param clr [in] 颜色数组（uint 类型，与数据数组长度一致，对应每个扇区的颜色）
    * @return bool - 操作结果：true=设置成功，false=失败（如数据数组为空或内存错误）
    * @note 调用者需确保三个数组长度一致，设置后自动触发图表重绘
    */
   bool              SeriesSet(const double &value[],const string &text[],const uint &clr[]);

   /**
    * @brief 添加一个扇区数据（追加到现有数据末尾）
    * @param value [in] 扇区数值（double 类型，必须>0，否则添加失败）
    * @param descr [in] 扇区描述符（string 类型，默认空字符串，建议填写以区分扇区）
    * @param clr [in] 扇区颜色（uint 类型，默认 0，自动分配 MT5 系统默认颜色）
    * @return bool - 操作结果：true=添加成功，false=失败（如数值≤0或内存错误）
    * @note 添加后自动触发图表重绘，小占比数据会被归为“其他”类别（由父类 m_threshold_drawing 控制）
    */
   bool              ValueAdd(const double value,const string descr="",const uint clr=0);

   /**
    * @brief 插入一个扇区数据（在指定位置添加）
    * @param pos [in] 插入位置索引（0 开始，需 < 当前数据量 m_data_total，否则失败）
    * @param value [in] 扇区数值（double 类型，必须>0，否则插入失败）
    * @param descr [in] 扇区描述符（string 类型，默认空字符串）
    * @param clr [in] 扇区颜色（uint 类型，默认 0，自动分配系统默认颜色）
    * @return bool - 操作结果：true=插入成功，false=失败（位置无效、数值≤0或内存错误）
    * @note 插入后后续数据索引自动后移，且触发图表重绘
    */
   bool              ValueInsert(const uint pos,const double value,const string descr="",const uint clr=0);

   /**
    * @brief 更新指定位置的扇区数据（修改数值、描述符或颜色）
    * @param pos [in] 扇区位置索引（0 开始，需 < m_data_total，否则失败）
    * @param value [in] 新扇区数值（double 类型，必须>0，否则更新失败）
    * @param descr [in] 新描述符（string 类型，默认 NULL，不修改原描述符）
    * @param clr [in] 新颜色（uint 类型，默认 0，不修改原颜色）
    * @return bool - 操作结果：true=更新成功，false=失败（位置无效、数值≤0或内存错误）
    * @note 更新后自动触发图表重绘，支持单独修改描述符或颜色（只需对应参数非默认值）
    */
   bool              ValueUpdate(const uint pos,const double value,const string descr=NULL,const uint clr=0);

   /**
    * @brief 删除指定位置的扇区数据
    * @param pos [in] 扇区位置索引（0 开始，需 < m_data_total 且 m_data_total >0，否则失败）
    * @return bool - 操作结果：true=删除成功，false=失败（位置无效或内存错误）
    * @note 删除后后续数据索引自动前移，“其他”类别会重新计算，且触发图表重绘
    */
   bool              ValueDelete(const uint pos);

protected:
   /**
    * @brief 绘制饼图完整内容（重写父类方法，核心绘制逻辑）
    * @note 核心流程：
    *       1. 计算饼图几何参数（圆心 m_x0/m_y0、半径 m_r，适配数据绘制区域）
    *       2. 绘制扇区（调用 DrawPie 绘制每个有效扇区，小占比数据合并为“其他”）
    *       3. 绘制数据标签（调用 LabelMake 生成标签文本，自动分左右布局，避免重叠）
    *       4. 绘制辅助元素（扇区边界线、标签连接线等）
    */
   virtual void      DrawChart(void);

   /**
    * @brief 绘制单个饼图扇区（内部辅助方法）
    * @param fi3 [in] 扇区起始角度（弧度，基于数据占比计算，0 对应右侧水平方向）
    * @param fi4 [in] 扇区结束角度（弧度，fi4 - fi3 为扇区角度，对应数据占比）
    * @param idx [in] 扇区索引（用于定位扇区在数据数组中的位置）
    * @param p [in/out] 扇区顶点坐标数组（存储扇区边缘与圆周的交点，用于绘制边界线）
    * @param clr [in] 扇区颜色（uint 类型，对应该扇区的填充色）
    * @note 逻辑：通过 Arc 绘制扇区弧线，通过 Fill 填充扇区内部，小扇区额外绘制半径线增强可读性
    */
   void              DrawPie(double fi3,double fi4,int idx,CPoint &p[],const uint clr);

   /**
    * @brief 生成饼图数据标签文本（内部辅助方法）
    * @param text [in] 扇区描述符（基础标签文本）
    * @param value [in] 扇区数值（用于生成数值标签或百分比标签）
    * @param to_left [in] 标签布局方向：true=左侧布局（文本右对齐），false=右侧布局（文本左对齐）
    * @return string - 最终标签文本（根据显示标志组合描述符、数值、百分比，如“分类A (50.00%)”）
    * @note 文本组合规则由父类显示标志控制（IS_SHOW_DESCRIPTORS/IS_SHOW_VALUE/IS_SHOW_PERCENT）
    */
   string            LabelMake(const string text,const double value,const bool to_left);
  };
//+------------------------------------------------------------------+